home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ir / zprot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-04  |  31.6 KB  |  1,154 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:`
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.    
  4. /*
  5.  
  6. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  7.  
  8.  
  9. #ifndef lint
  10. static char *RCSid = "$Header: /usr/local/ls6/src+data/src/freeWAIS-sf/ir/RCS/zprot.c,v 1.4 1994/08/05 07:13:01 pfeifer Exp $";
  11. #endif
  12.  
  13. /* Change log:
  14.  * $Log: zprot.c,v $
  15.  * Revision 1.4  1994/08/05  07:13:01  pfeifer
  16.  * Release beta 04
  17.  *
  18.  * Revision 1.3  1994/05/20  12:58:19  pfeifer
  19.  * beta
  20.  *
  21.  * Revision 1.2  1994/03/08  21:07:22  pfeifer
  22.  * Patchlevel 04
  23.  *
  24.  * Revision 1.1  1993/02/16  15:05:35  freewais
  25.  * Initial revision
  26.  *
  27.  * Revision 1.4  92/02/12  13:59:51  jonathan
  28.  * Added "$Log" so RCS will put the log message in the header
  29.  * 
  30.  * 
  31.   
  32.    3.26.90    Harry Morris, morris@think.com
  33.    3.30.90  Harry Morris - Changed any->bits to any->bytes
  34.    4.11.90  HWM - generalized conditional includes (see c-dialect.h)
  35. */
  36.  
  37. #define _C_Z39_50_
  38.  
  39. #include "zprot.h"
  40.  
  41. #include "zutil.h"
  42. #include "cutil.h"
  43. /*#include <string.h>*/
  44.  
  45. #ifndef ANSI_LIKE
  46. #include "ustubs.h"
  47. #endif
  48.  
  49. #define RESERVE_SPACE_FOR_HEADER(spaceLeft)        \
  50.     *spaceLeft -= HEADER_LEN;
  51.     
  52. #define RELEASE_HEADER_SPACE(spaceLeft)            \
  53.     if (*spaceLeft > 0)                            \
  54.       *spaceLeft += HEADER_LEN;
  55.     
  56. /*----------------------------------------------------------------------*/
  57.  
  58. InitAPDU* 
  59. makeInitAPDU(search,
  60.          present,
  61.          deleteIt,
  62.          accessControl,
  63.          resourceControl,
  64.          prefSize,
  65.          maxMsgSize,
  66.          auth,
  67.          id,
  68.          name,
  69.          version,
  70.          refID,
  71.          userInfo)
  72. boolean search;
  73. boolean present;
  74. boolean deleteIt;
  75. boolean accessControl;
  76. boolean resourceControl;
  77. long prefSize;
  78. long maxMsgSize;
  79. char* auth;
  80. char* id;
  81. char* name;
  82. char* version;
  83. any* refID;
  84. void* userInfo;
  85.  
  86. /* build an init APDU with user specified information */
  87.   InitAPDU* init = (InitAPDU*)s_malloc((size_t)sizeof(InitAPDU));
  88.  
  89.   init->PDUType = initAPDU;
  90.   init->willSearch = search;
  91.   init->willPresent = present;
  92.   init->willDelete = deleteIt;
  93.   init->supportAccessControl = accessControl;
  94.   init->supportResourceControl = resourceControl;
  95.   init->PreferredMessageSize = prefSize;
  96.   init->MaximumRecordSize = maxMsgSize;
  97.   init->IDAuthentication = s_strdup(auth);
  98.   init->ImplementationID = s_strdup(id);
  99.   init->ImplementationName = s_strdup(name);
  100.   init->ImplementationVersion = s_strdup(version);
  101.   init->ReferenceID = duplicateAny(refID);
  102.   init->UserInformationField = userInfo; /* not copied */
  103.   
  104.   return(init);
  105. }
  106.  
  107. /*----------------------------------------------------------------------*/
  108.  
  109. void 
  110. freeInitAPDU(init)
  111. InitAPDU* init;
  112. /* free an initAPDU */
  113. {
  114.   s_free(init->IDAuthentication);
  115.   s_free(init->ImplementationID);
  116.   s_free(init->ImplementationName);
  117.   s_free(init->ImplementationVersion);
  118.   freeAny(init->ReferenceID);
  119.   s_free(init);
  120. }
  121.  
  122. /*----------------------------------------------------------------------*/
  123.  
  124. char* 
  125. writeInitAPDU(init,buffer,len)
  126. InitAPDU* init;
  127. char* buffer;
  128. long* len;
  129. /* write the init to a buffer, adding system information */
  130. {
  131.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  132.   long size;
  133.   bit_map* optionsBM = NULL;
  134.  
  135.   RESERVE_SPACE_FOR_HEADER(len);
  136.   
  137.   buf = writePDUType(init->PDUType,buf,len);
  138.   
  139.   buf = writeProtocolVersion(buf,len);
  140.   
  141.   optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
  142.                          init->willDelete,init->supportAccessControl,
  143.                          init->supportResourceControl);
  144.   buf = writeBitMap(optionsBM,DT_Options,buf,len);
  145.   freeBitMap(optionsBM);
  146.  
  147.   buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
  148.   buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
  149.   buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
  150.   buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
  151.   buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
  152.   buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
  153.   buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
  154.   
  155.   /* go back and write the header-length-indicator */
  156.   RELEASE_HEADER_SPACE(len);
  157.   size = buf - buffer - HEADER_LEN; 
  158.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  159.  
  160.   if (init->UserInformationField != NULL)
  161.     buf = writeInitInfo(init,buf,len);   
  162.     
  163.   return(buf); 
  164. }
  165.  
  166. /*----------------------------------------------------------------------*/
  167.  
  168. char* 
  169. readInitAPDU(init,buffer)
  170. InitAPDU** init;
  171. char* buffer;
  172. {
  173.   char* buf = buffer;
  174.   boolean search,present,delete,accessControl,resourceControl;
  175.   long prefSize,maxMsgSize;
  176.   char *auth,*id,*name,*version;
  177.   long size; 
  178.   pdu_type pduType;
  179.   bit_map* versionBM = NULL;
  180.   bit_map* optionsBM = NULL;
  181.   any *refID = NULL;
  182.   void* userInfo = NULL;
  183.   
  184.   auth = id = name = version = NULL;
  185.   
  186.   /* read required part */
  187.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  188.   buf = readPDUType(&pduType,buf);
  189.   buf = readBitMap(&versionBM,buf); 
  190.   buf = readBitMap(&optionsBM,buf);
  191.   buf = readNum(&prefSize,buf);
  192.   buf = readNum(&maxMsgSize,buf);
  193.   
  194.   /* decode optionsBM */
  195.   search = bitAtPos(0L,optionsBM);
  196.   present = bitAtPos(1L,optionsBM);
  197.   delete = bitAtPos(2L,optionsBM);
  198.   accessControl = bitAtPos(3L,optionsBM);
  199.   resourceControl = bitAtPos(4L,optionsBM);
  200.   
  201.   /* read optional part */
  202.   while (buf < (buffer + size + HEADER_LEN)) 
  203.     { data_tag tag = peekTag(buf);
  204.       switch (tag)
  205.     { case DT_IDAuthentication:
  206.         buf = readString(&auth,buf);
  207.         break;
  208.       case DT_ImplementationID:
  209.         buf = readString(&id,buf);
  210.         break;
  211.       case DT_ImplementationName:
  212.         buf = readString(&name,buf);
  213.         break;
  214.       case DT_ImplementationVersion:
  215.         buf = readString(&version,buf);
  216.         break;
  217.       case DT_ReferenceID:
  218.         buf = readAny(&refID,buf);
  219.         break;
  220.       default:
  221.         freeBitMap(versionBM);
  222.         freeBitMap(optionsBM);
  223.         s_free(auth);
  224.         s_free(id);
  225.         s_free(name);
  226.         s_free(version);
  227.         freeAny(refID);
  228.         REPORT_READ_ERROR(buf);
  229.         break;
  230.       }
  231.     }
  232.  
  233.   buf = readInitInfo(&userInfo,buf);
  234.   s_free(userInfo);
  235.   if (buf == NULL)
  236.     { freeBitMap(versionBM);
  237.       freeBitMap(optionsBM);
  238.       s_free(auth);
  239.       s_free(id);
  240.       s_free(name);
  241.       s_free(version);
  242.       freeAny(refID);
  243.     }
  244.   RETURN_ON_NULL(buf);
  245.  
  246.   /* construct the basic init object */
  247.   *init = makeInitAPDU(search,present,delete,accessControl,resourceControl,
  248.                        prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
  249.                           
  250.   freeBitMap(versionBM);
  251.   freeBitMap(optionsBM);
  252.   s_free(auth);
  253.   s_free(id);
  254.   s_free(name);
  255.   s_free(version);
  256.   freeAny(refID);
  257.   
  258.   return(buf);
  259. }
  260.  
  261. /*----------------------------------------------------------------------*/
  262.  
  263. InitResponseAPDU* 
  264. makeInitResponseAPDU(result,
  265.              search,
  266.              present,
  267.              deleteIt,
  268.              accessControl,
  269.              resourceControl,
  270.              prefSize,
  271.              maxMsgSize,
  272.              auth,
  273.              id,
  274.              name,
  275.              version,
  276.              refID,
  277.              userInfo)
  278. boolean result;
  279. boolean search;
  280. boolean present;
  281. boolean deleteIt;
  282. boolean accessControl;
  283. boolean resourceControl;
  284. long prefSize;
  285. long maxMsgSize;
  286. char* auth;
  287. char* id;
  288. char* name;
  289. char* version;
  290. any* refID;
  291. void* userInfo;
  292. /* build an initResponse APDU with user specified information */
  293.   InitResponseAPDU* init = (InitResponseAPDU*)s_malloc((size_t)sizeof(InitResponseAPDU));
  294.  
  295.   init->PDUType = initResponseAPDU;
  296.   init->Result = result;
  297.   init->willSearch = search;
  298.   init->willPresent = present;
  299.   init->willDelete = deleteIt;
  300.   init->supportAccessControl = accessControl;
  301.   init->supportResourceControl = resourceControl;
  302.   init->PreferredMessageSize = prefSize;
  303.   init->MaximumRecordSize = maxMsgSize;
  304.   init->IDAuthentication = s_strdup(auth);
  305.   init->ImplementationID = s_strdup(id);
  306.   init->ImplementationName = s_strdup(name);
  307.   init->ImplementationVersion = s_strdup(version);
  308.   init->ReferenceID = duplicateAny(refID);
  309.   init->UserInformationField = userInfo; /* not copied! */
  310.   
  311.   return(init);
  312. }
  313.  
  314. /*----------------------------------------------------------------------*/
  315.  
  316. void 
  317. freeInitResponseAPDU(init)
  318. InitResponseAPDU* init;
  319. /* free an initAPDU */
  320. {
  321.   s_free(init->IDAuthentication);
  322.   s_free(init->ImplementationID);
  323.   s_free(init->ImplementationName);
  324.   s_free(init->ImplementationVersion);
  325.   freeAny(init->ReferenceID);
  326.   s_free(init);
  327. }
  328.  
  329. /*----------------------------------------------------------------------*/
  330.  
  331. char* 
  332. writeInitResponseAPDU(init,buffer,len)
  333. InitResponseAPDU* init;
  334. char* buffer;
  335. long* len;
  336. /* write the initResponse to a buffer, adding system information */
  337.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  338.   long size;
  339.   bit_map* optionsBM = NULL;
  340.  
  341.   RESERVE_SPACE_FOR_HEADER(len);
  342.   
  343.   buf = writePDUType(init->PDUType,buf,len);
  344.   buf = writeBoolean(init->Result,buf,len);
  345.   buf = writeProtocolVersion(buf,len);
  346.   
  347.   optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
  348.                          init->willDelete,init->supportAccessControl,
  349.                          init->supportResourceControl);
  350.   buf = writeBitMap(optionsBM,DT_Options,buf,len);
  351.   freeBitMap(optionsBM);
  352.  
  353.   buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
  354.   buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
  355.   buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
  356.   buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
  357.   buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
  358.   buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
  359.   buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
  360.   
  361.   /* go back and write the header-length-indicator */
  362.   RELEASE_HEADER_SPACE(len);
  363.   size = buf - buffer - HEADER_LEN; 
  364.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  365.  
  366.   if (init->UserInformationField != NULL)
  367.     buf = writeInitResponseInfo(init,buf,len);   
  368.     
  369.   return(buf);
  370. }
  371.  
  372. /*----------------------------------------------------------------------*/
  373.  
  374. char* 
  375. readInitResponseAPDU(init,buffer)
  376. InitResponseAPDU** init;
  377. char* buffer;
  378. {
  379.   char* buf = buffer;
  380.   boolean search,present,delete,accessControl,resourceControl;
  381.   long prefSize,maxMsgSize;
  382.   char *auth,*id,*name,*version;
  383.   long size; 
  384.   pdu_type pduType;
  385.   bit_map* versionBM = NULL;
  386.   bit_map* optionsBM = NULL;
  387.   boolean result;
  388.   any *refID = NULL;
  389.   void* userInfo = NULL;
  390.   
  391.   auth = id = name = version = NULL;
  392.   refID = NULL;
  393.   
  394.   /* read required part */
  395.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  396.   buf = readPDUType(&pduType,buf);
  397.   buf = readBoolean(&result,buf);
  398.   buf = readBitMap(&versionBM,buf); 
  399.   buf = readBitMap(&optionsBM,buf);
  400.   buf = readNum(&prefSize,buf);
  401.   buf = readNum(&maxMsgSize,buf);
  402.   
  403.   /* decode optionsBM */
  404.   search = bitAtPos(0L,optionsBM);
  405.   present = bitAtPos(1L,optionsBM);
  406.   delete = bitAtPos(2L,optionsBM);
  407.   accessControl = bitAtPos(3L,optionsBM);
  408.   resourceControl = bitAtPos(4L,optionsBM);
  409.   
  410.   /* read optional part */
  411.   while (buf < (buffer + size + HEADER_LEN)) 
  412.     { data_tag tag = peekTag(buf);
  413.       switch (tag)
  414.     { case DT_IDAuthentication:
  415.         buf = readString(&auth,buf);
  416.         break;
  417.       case DT_ImplementationID:
  418.         buf = readString(&id,buf);
  419.         break;
  420.       case DT_ImplementationName:
  421.         buf = readString(&name,buf);
  422.         break;
  423.       case DT_ImplementationVersion:
  424.         buf = readString(&version,buf);
  425.         break;
  426.       case DT_ReferenceID:
  427.         buf = readAny(&refID,buf);
  428.         break;
  429.       default:
  430.         freeBitMap(versionBM);
  431.         freeBitMap(optionsBM);
  432.         s_free(auth);
  433.         s_free(id);
  434.         s_free(name);
  435.         s_free(version);
  436.         freeAny(refID);
  437.         REPORT_READ_ERROR(buf);
  438.         break;
  439.       }
  440.     }
  441.  
  442.   buf = readInitResponseInfo(&userInfo,buf);
  443.   if (buf == NULL)
  444.     { freeBitMap(versionBM);
  445.       freeBitMap(optionsBM);
  446.       s_free(auth);
  447.       s_free(id);
  448.       s_free(name);
  449.       s_free(version);
  450.       freeAny(refID);
  451.     }
  452.   RETURN_ON_NULL(buf);
  453.   
  454.   /* construct the basic init object */
  455.   *init = makeInitResponseAPDU(result,
  456.                    search,present,delete,accessControl,resourceControl,
  457.                    prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
  458.                                           
  459.   freeBitMap(versionBM);
  460.   freeBitMap(optionsBM);
  461.   s_free(auth);
  462.   s_free(id);
  463.   s_free(name);
  464.   s_free(version);
  465.   freeAny(refID);
  466.   
  467.   return(buf);
  468. }
  469.  
  470. /*----------------------------------------------------------------------*/
  471.  
  472. InitResponseAPDU* 
  473. replyToInitAPDU(init,result,userInfo)
  474. InitAPDU* init;
  475. boolean result;
  476. void* userInfo;
  477. /* respond to an init message in the default way - echoing back
  478.    the init info 
  479.  */
  480. {
  481.   InitResponseAPDU* initResp;
  482.   initResp = makeInitResponseAPDU(result,
  483.                   init->willSearch,init->willPresent,init->willDelete,
  484.                   init->supportAccessControl,init->supportResourceControl,
  485.                   init->PreferredMessageSize,init->MaximumRecordSize,
  486.                   init->IDAuthentication,defaultImplementationID(),defaultImplementationName(),
  487.                   defaultImplementationVersion(),
  488.                   init->ReferenceID,userInfo);
  489.   return(initResp);
  490. }
  491.  
  492. /*----------------------------------------------------------------------*/
  493.  
  494. SearchAPDU* 
  495. makeSearchAPDU(small,
  496.            large,
  497.            medium,
  498.            replace,
  499.            name,
  500.            databases,
  501.            type,
  502.            elements,
  503.            refID,
  504.            queryInfo)
  505. long small;
  506. long large;
  507. long medium;
  508. boolean replace;
  509. char* name;
  510. char** databases;
  511. char* type;
  512. char** elements;
  513. any* refID;
  514. void* queryInfo;
  515. {
  516.   char* ptr = NULL;
  517.   long i;
  518.   SearchAPDU* query = (SearchAPDU*)s_malloc((size_t)sizeof(SearchAPDU));
  519.   query->PDUType = searchAPDU;
  520.   query->SmallSetUpperBound = small;
  521.   query->LargeSetLowerBound = large;
  522.   query->MediumSetPresentNumber = medium;
  523.   query->ReplaceIndicator = replace;
  524.   query->ResultSetName = s_strdup(name);
  525.   query->DatabaseNames = NULL; 
  526.   if (databases != NULL)
  527.     { for (i = 0, ptr = databases[i]; ptr != NULL; ptr = databases[++i])
  528.     { if (query->DatabaseNames == NULL)
  529.         query->DatabaseNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
  530.         else
  531.           query->DatabaseNames = (char**)s_realloc((char*)query->DatabaseNames,
  532.                            (size_t)(sizeof(char*) * (i + 2)));
  533.         query->DatabaseNames[i] = s_strdup(ptr);
  534.         query->DatabaseNames[i+1] = NULL;
  535.       }
  536.       }
  537.   query->QueryType = s_strdup(type);
  538.   query->ElementSetNames = NULL; 
  539.   if (elements != NULL)
  540.     { for (i = 0, ptr = elements[i]; ptr != NULL; ptr = elements[++i])
  541.     { if (query->ElementSetNames == NULL)
  542.         query->ElementSetNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
  543.         else
  544.           query->ElementSetNames = (char**)s_realloc((char*)query->ElementSetNames,
  545.                              (size_t)(sizeof(char*) * (i + 2)));
  546.         query->ElementSetNames[i] = s_strdup(ptr);
  547.         query->ElementSetNames[i+1] = NULL;
  548.       }
  549.       }
  550.   query->ReferenceID = duplicateAny(refID);
  551.   query->Query = queryInfo;    /* not copied! */
  552.   return(query);
  553. }
  554.  
  555. /*----------------------------------------------------------------------*/
  556.  
  557. void 
  558. freeSearchAPDU(query)
  559. SearchAPDU* query;
  560. {
  561.   s_free(query->ResultSetName);
  562.   s_free(query->QueryType);
  563.   doList((void**)query->DatabaseNames,fs_free); /* can't use the macro here ! */
  564.   s_free(query->DatabaseNames);
  565.   doList((void**)query->ElementSetNames,fs_free); /* can't use the macro here ! */
  566.   s_free(query->ElementSetNames);
  567.   freeAny(query->ReferenceID);
  568.   s_free(query);
  569. }
  570.  
  571. /*----------------------------------------------------------------------*/
  572.  
  573. #define DB_DELIMITER     "\037"     /* hex 1F occurs between each database name */
  574. #define ES_DELIMITER_1     "\037"     /* separates database name from element name */
  575. #define ES_DELIMITER_2     "\036"     /* hex 1E separates <db,es> groups from one another */
  576.  
  577. char* 
  578. writeSearchAPDU(query,buffer,len)
  579. SearchAPDU* query;
  580. char* buffer;
  581. long* len;
  582.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  583.   long size,i;
  584.   char* ptr = NULL;
  585.   char* scratch = NULL;
  586.  
  587.   RESERVE_SPACE_FOR_HEADER(len);
  588.   
  589.   buf = writePDUType(query->PDUType,buf,len);
  590.   buf = writeBinaryInteger(query->SmallSetUpperBound,(size_t)3,buf,len);
  591.   buf = writeBinaryInteger(query->LargeSetLowerBound,(size_t)3,buf,len);
  592.   buf = writeBinaryInteger(query->MediumSetPresentNumber,(size_t)3,buf,len);
  593.   buf = writeBoolean(query->ReplaceIndicator,buf,len);
  594.   buf = writeString(query->ResultSetName,DT_ResultSetName,buf,len);
  595.   /* write database names */
  596.   if (query->DatabaseNames != NULL)
  597.     { for (i = 0,scratch = NULL, ptr = query->DatabaseNames[i]; ptr != NULL; ptr = query->DatabaseNames[++i])
  598.     { if (scratch == NULL)
  599.         scratch = s_strdup(ptr);
  600.         else
  601.       { size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + 3);
  602.         scratch = (char*)s_realloc(scratch,newScratchSize);
  603.         s_strncat(scratch,DB_DELIMITER,2L,newScratchSize);
  604.         s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
  605.       }
  606.       }
  607.     buf = writeString(scratch,DT_DatabaseNames,buf,len);
  608.     s_free(scratch);
  609.       }
  610.   buf = writeString(query->QueryType,DT_QueryType,buf,len);
  611.   /* write element set names */
  612.   if (query->ElementSetNames != NULL)
  613.     { for (i = 0,scratch = NULL, ptr = query->ElementSetNames[i]; ptr != NULL; ptr = query->ElementSetNames[++i])
  614.     { if (scratch == NULL)
  615.         { if (query->ElementSetNames[i+1] == NULL) /* there is a single element set name */
  616.         { scratch = (char*)s_malloc((size_t)strlen(ptr) + 3);
  617.           strncpy(scratch,ES_DELIMITER_1,2);
  618.           s_strncat(scratch,ptr,strlen(ptr) + 1,strlen(ptr) + 2);
  619.         }
  620.         else        /* this is the first of a series of element set names */
  621.           { size_t newScratchSize = (size_t)(strlen(ptr) + strlen(query->ElementSetNames[i + 1]) + 3);
  622.         scratch = s_strdup(ptr); /* the database name */
  623.         ptr = query->ElementSetNames[++i]; /* the element set name */
  624.         scratch = (char*)s_realloc(scratch,newScratchSize);
  625.         s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
  626.         s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize); 
  627.           }
  628.           }
  629.         else
  630.       { char* esPtr = query->ElementSetNames[++i]; /* the element set name */
  631.         size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + strlen(esPtr) + 3);
  632.         scratch = (char*)s_realloc(scratch,newScratchSize);
  633.         s_strncat(scratch,ES_DELIMITER_2,2L,newScratchSize);
  634.         s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
  635.         s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
  636.         s_strncat(scratch,esPtr,strlen(esPtr) + 1,newScratchSize); 
  637.       }
  638.       }
  639.     buf = writeString(scratch,DT_ElementSetNames,buf,len);
  640.     s_free(scratch);
  641.       }                        
  642.   buf = writeAny(query->ReferenceID,DT_ReferenceID,buf,len);
  643.     
  644.   /* go back and write the header-length-indicator */
  645.   RELEASE_HEADER_SPACE(len);
  646.   size = buf - buffer - HEADER_LEN; 
  647.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  648.  
  649.   if (query->Query != NULL)
  650.     buf = writeSearchInfo(query,buf,len);    
  651.     
  652.   return(buf);
  653. }
  654.  
  655. /*----------------------------------------------------------------------*/
  656.  
  657. char*
  658. readSearchAPDU(query,buffer)
  659. SearchAPDU** query;
  660. char* buffer;
  661. {
  662.   char* buf = buffer;
  663.   long size;
  664.   pdu_type pduType;
  665.   long small,large,medium,numItems;
  666.   boolean replace;
  667.   char *name,*databaseNames,*type,*elements;
  668.   char **dbList,**elemList;
  669.   any *refID;
  670.   void* userInfo = NULL;
  671.   
  672.   name = databaseNames = type = elements = NULL;
  673.   dbList = elemList = NULL;
  674.   refID = NULL;
  675.  
  676.   /* read required part */
  677.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  678.   buf = readPDUType(&pduType,buf);
  679.   buf = readBinaryInteger(&small,(size_t)3,buf);
  680.   buf = readBinaryInteger(&large,(size_t)3,buf);
  681.   buf = readBinaryInteger(&medium,(size_t)3,buf);
  682.   buf = readBoolean(&replace,buf);
  683.   
  684.   /* read optional part */
  685.   while (buf < (buffer + size + HEADER_LEN)) 
  686.     { data_tag tag = peekTag(buf);
  687.       switch (tag)
  688.     { case DT_ResultSetName:
  689.         buf = readString(&name,buf);
  690.         break;
  691.       case DT_DatabaseNames:
  692.         {            /* parse the database names */
  693.           char *tok;
  694.           buf = readString(&databaseNames,buf);
  695.           tok = strtok(databaseNames,DB_DELIMITER);
  696.           numItems = 0;
  697.           while (tok != NULL)
  698.         { if (dbList == NULL)
  699.             dbList = (char**)s_malloc((size_t)(sizeof(char*) * 2));
  700.         else
  701.           dbList = (char**)s_realloc((char*)dbList,(size_t)(sizeof(char*) * (numItems+2)));
  702.             dbList[numItems++] = s_strdup(tok);
  703.             dbList[numItems] = NULL;
  704.             tok = strtok(NULL,DB_DELIMITER);
  705.           }
  706.         }
  707.         break;
  708.       case DT_QueryType:
  709.         buf = readString(&type,buf);
  710.         break;
  711.       case DT_ElementSetNames:
  712.         {            /* parse the element set names */
  713.           char *tok;
  714.           buf = readString(&elements,buf);
  715.           if (elements[0] == ES_DELIMITER_1[0]) /* this is a single element w/ no db */
  716.         { elemList = (char**)s_malloc((size_t)(sizeof(char*) * 2));
  717.           elemList[0] = s_strdup(elements);
  718.           elemList[1] = NULL;
  719.         }
  720.           else        /* its a group of <DB/ES> pairs */
  721.         { char* esTok = NULL;
  722.           tok = strtok(elements,ES_DELIMITER_1); /* db name */
  723.           esTok = strtok(NULL,ES_DELIMITER_2); /* es name */
  724.           numItems = 0;
  725.           while (tok != NULL)
  726.             { if (elemList == NULL)
  727.             elemList = (char**)s_malloc((size_t)(sizeof(char*) * 3));
  728.             else
  729.               elemList = (char**)s_realloc((char*)elemList,(size_t)(sizeof(char*) * (numItems * 2 + 1)));
  730.             elemList[numItems++] = s_strdup(tok);
  731.             elemList[numItems++] = s_strdup(esTok);
  732.             elemList[numItems] = NULL;
  733.             tok = strtok(NULL,ES_DELIMITER_1);
  734.             esTok = strtok(NULL,ES_DELIMITER_2);
  735.               } 
  736.         }
  737.         }
  738.         break;
  739.       case DT_ReferenceID:
  740.         buf = readAny(&refID,buf);
  741.         break;
  742.       default:
  743.         s_free(name);
  744.         s_free(type);
  745.         s_free(databaseNames);
  746.         doList((void**)dbList,fs_free);
  747.         s_free(dbList);
  748.         s_free(elements);
  749.         doList((void**)elemList,fs_free);
  750.         s_free(elemList);
  751.         freeAny(refID);
  752.         REPORT_READ_ERROR(buf);
  753.         break;
  754.       }
  755.     }
  756.   
  757.   buf = readSearchInfo(&userInfo,buf);
  758.   if (buf == NULL)
  759.     { s_free(name);
  760.       s_free(type);
  761.       s_free(databaseNames);
  762.       doList((void**)dbList,fs_free);
  763.       s_free(dbList);
  764.       s_free(elements);
  765.       doList((void**)elemList,fs_free);
  766.       s_free(elemList);
  767.       freeAny(refID);
  768.     }
  769.   RETURN_ON_NULL(buf);
  770.     
  771.   /* construct the search object */
  772.   *query = makeSearchAPDU(small,large,medium,replace,name,dbList,type,elemList,refID,userInfo);
  773.  
  774.   s_free(name);
  775.   s_free(type);
  776.   s_free(databaseNames);
  777.   doList((void**)dbList,fs_free);
  778.   s_free(dbList);
  779.   s_free(elements);
  780.   doList((void**)elemList,fs_free);
  781.   s_free(elemList);
  782.   freeAny(refID);
  783.   
  784.   return(buf);
  785. }
  786.  
  787. /*----------------------------------------------------------------------*/
  788.  
  789. SearchResponseAPDU* 
  790. makeSearchResponseAPDU(result,count,recordsReturned,nextPos,resultStatus,
  791.                presentStatus,refID,records)
  792. long result;
  793. long count;
  794. long recordsReturned;
  795. long nextPos;
  796. long resultStatus;
  797. long presentStatus;
  798. any* refID;
  799. void* records;
  800. {
  801.   SearchResponseAPDU* query = (SearchResponseAPDU*)s_malloc((size_t)sizeof(SearchResponseAPDU));
  802.   query->PDUType = searchResponseAPDU;
  803.   query->SearchStatus = result;
  804.   query->ResultCount = count;
  805.   query->NumberOfRecordsReturned = recordsReturned;
  806.   query->NextResultSetPosition = nextPos;
  807.   query->ResultSetStatus = resultStatus;
  808.   query->PresentStatus = presentStatus;
  809.   query->ReferenceID = duplicateAny(refID);
  810.   query->DatabaseDiagnosticRecords = records;
  811.   return(query);  
  812. }
  813.  
  814. /*----------------------------------------------------------------------*/
  815.  
  816. void 
  817. freeSearchResponseAPDU(queryResponse)
  818. SearchResponseAPDU* queryResponse;
  819. {
  820.   freeAny(queryResponse->ReferenceID);
  821.   s_free(queryResponse);
  822. }
  823.  
  824. /*----------------------------------------------------------------------*/
  825.  
  826. char* 
  827. writeSearchResponseAPDU(queryResponse,buffer,len)
  828. SearchResponseAPDU* queryResponse;
  829. char* buffer;
  830. long* len;
  831. {
  832.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  833.   long size;
  834.  
  835.   RESERVE_SPACE_FOR_HEADER(len);
  836.   
  837.   buf = writePDUType(queryResponse->PDUType,buf,len);
  838.   buf = writeBinaryInteger(queryResponse->SearchStatus,(size_t)1,buf,len);
  839.   buf = writeBinaryInteger(queryResponse->ResultCount,(size_t)3,buf,len);
  840.   buf = writeBinaryInteger(queryResponse->NumberOfRecordsReturned,(size_t)3,buf,len);
  841.   buf = writeBinaryInteger(queryResponse->NextResultSetPosition,(size_t)3,buf,len);
  842.   buf = writeNum(queryResponse->ResultSetStatus,DT_ResultSetStatus,buf,len);
  843.   buf = writeNum(queryResponse->PresentStatus,DT_PresentStatus,buf,len);
  844.   buf = writeAny(queryResponse->ReferenceID,DT_ReferenceID,buf,len);
  845.     
  846.   /* go back and write the header-length-indicator */
  847.   RELEASE_HEADER_SPACE(len);
  848.   size = buf - buffer - HEADER_LEN; 
  849.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  850.  
  851.   if (queryResponse->DatabaseDiagnosticRecords != NULL)
  852.     buf = writeSearchResponseInfo(queryResponse,buf,len);    
  853.     
  854.   return(buf);
  855. }
  856.  
  857. /*----------------------------------------------------------------------*/
  858.  
  859. char* 
  860. readSearchResponseAPDU(queryResponse,buffer)
  861. SearchResponseAPDU** queryResponse;
  862. char* buffer;
  863. {
  864.   char* buf = buffer;
  865.   long size;
  866.   pdu_type pduType;
  867.   long result,count,recordsReturned,nextPos;
  868.   long resultStatus,presentStatus;
  869.   any *refID = NULL;
  870.   void* userInfo = NULL;
  871.   
  872.   /* read required part */
  873.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  874.   buf = readPDUType(&pduType,buf);
  875.   buf = readBinaryInteger(&result,(size_t)1,buf);
  876.   buf = readBinaryInteger(&count,(size_t)3,buf);
  877.   buf = readBinaryInteger(&recordsReturned,(size_t)3,buf);
  878.   buf = readBinaryInteger(&nextPos,(size_t)3,buf);
  879.   
  880.   resultStatus = presentStatus = UNUSED;
  881.   refID = NULL;
  882.  
  883.   /* read optional part */
  884.   while (buf < (buffer + size + HEADER_LEN)) 
  885.     { data_tag tag = peekTag(buf);
  886.       switch (tag)
  887.     { case DT_ResultSetStatus:
  888.         buf = readNum(&resultStatus,buf);
  889.         break;
  890.       case DT_PresentStatus:
  891.         buf = readNum(&presentStatus,buf);
  892.         break;
  893.       case DT_ReferenceID:
  894.         buf = readAny(&refID,buf);
  895.         break;
  896.       default:
  897.         freeAny(refID);
  898.         REPORT_READ_ERROR(buf);
  899.         break;
  900.       }
  901.     }
  902.   
  903.   buf = readSearchResponseInfo(&userInfo,buf);
  904.   if (buf == NULL)
  905.     freeAny(refID);
  906.   RETURN_ON_NULL(buf);
  907.   
  908.   /* construct the search object */
  909.   *queryResponse = makeSearchResponseAPDU(result,count,recordsReturned,nextPos,
  910.                       (long)resultStatus,(long)presentStatus,refID,userInfo);
  911.  
  912.   freeAny(refID);
  913.   
  914.   return(buf);
  915. }
  916.  
  917. #ifdef NOTUSED
  918. /*----------------------------------------------------------------------*/
  919.  
  920.  
  921. PresentAPDU* 
  922. makePresentAPDU(recsReq,startPos,resultID,refID,info)
  923. long recsReq;
  924. long startPos;
  925. char* resultID;
  926. any* refID;
  927. void* info;
  928. {
  929.   PresentAPDU* present = (PresentAPDU*)s_malloc((size_t)sizeof(PresentAPDU));
  930.   present->PDUType = presentAPDU;
  931.   present->NumberOfRecordsRequested = recsReq;
  932.   present->ResultSetStartPosition = startPos;
  933.   present->ResultSetID = s_strdup(resultID);
  934.   present->ElementSetNames = NULL; /* XXX for now */
  935.   present->ReferenceID = duplicateAny(refID);
  936.   present->PresentInfo = info;
  937.   return(present);  
  938. }
  939.  
  940. /*----------------------------------------------------------------------*/
  941.  
  942. void 
  943. freePresentAPDU(present)
  944. PresentAPDU* present;
  945. {
  946.   /* handle element set names */ 
  947.   s_free(present->ResultSetID);
  948.   freeAny(present->ReferenceID);
  949.   s_free(present);
  950. }
  951.  
  952. /*----------------------------------------------------------------------*/
  953.  
  954. char* 
  955. writePresentAPDU(present,buffer,len)
  956. PresentAPDU* present;
  957. char* buffer;
  958. long* len;
  959. {
  960.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  961.   long size;
  962.  
  963.   RESERVE_SPACE_FOR_HEADER(len);
  964.   
  965.   buf = writePDUType(present->PDUType,buf,len);
  966.   buf = writeBinaryInteger(present->NumberOfRecordsRequested,(size_t)3,buf,len);
  967.   buf = writeBinaryInteger(present->ResultSetStartPosition,(size_t)3,buf,len);
  968.   buf = writeString(present->ResultSetID,DT_ResultSetID,buf,len); 
  969.   /* handle element set names */
  970.   buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
  971.     
  972.   /* go back and write the header-length-indicator */
  973.   RELEASE_HEADER_SPACE(len);
  974.   size = buf - buffer - HEADER_LEN; 
  975.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  976.  
  977.   if (present->PresentInfo != NULL)
  978.     buf = writePresentInfo(present,buf,len);   
  979.     
  980.   return(buf); 
  981. }
  982.  
  983. /*----------------------------------------------------------------------*/
  984.  
  985. char* 
  986. readPresentAPDU(present,buffer)
  987. PresentAPDU** present;
  988. char* buffer;
  989. {
  990.   char* buf = buffer;
  991.   long size;
  992.   pdu_type pduType;
  993.   long recsReq,startPos;
  994.   char* resultID = NULL;
  995.   any *refID = NULL;
  996.   void* userInfo = NULL;
  997.   
  998.   /* read required part */
  999.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  1000.   buf = readPDUType(&pduType,buf);
  1001.   buf = readBinaryInteger(&recsReq,(size_t)3,buf);
  1002.   buf = readBinaryInteger(&startPos,(size_t)3,buf);
  1003.   buf = readString(&resultID,buf);
  1004.   
  1005.   /* read optional part */
  1006.   while (buf < (buffer + size + HEADER_LEN)) 
  1007.    { data_tag tag = peekTag(buf);
  1008.      switch (tag)
  1009.       { case DT_ReferenceID:
  1010.           buf = readAny(&refID,buf);
  1011.           break;
  1012.         default:
  1013.           s_free(resultID);
  1014.           freeAny(refID);
  1015.           REPORT_READ_ERROR(buf);
  1016.           break;
  1017.       }
  1018.    }
  1019.   
  1020.   buf = readPresentInfo(&userInfo,buf);
  1021.   if (buf == NULL)
  1022.    { s_free(resultID);
  1023.      freeAny(refID);
  1024.    }
  1025.   RETURN_ON_NULL(buf);
  1026.  
  1027.   /* construct the present object */
  1028.   *present = makePresentAPDU(recsReq,startPos,resultID,refID,userInfo);
  1029.  
  1030.   s_free(resultID);
  1031.   freeAny(refID);
  1032.   
  1033.   return(buf);
  1034. }
  1035.  
  1036. /*----------------------------------------------------------------------*/
  1037.  
  1038.  
  1039. PresentResponseAPDU* 
  1040. makePresentResponseAPDU(status,recsRet,nextPos,refID,records)
  1041. boolean status;
  1042. long recsRet;
  1043. long nextPos;
  1044. any* refID;
  1045. void* records;
  1046. {
  1047.   PresentResponseAPDU* present = (PresentResponseAPDU*)s_malloc((size_t)sizeof(PresentResponseAPDU));
  1048.   present->PDUType = presentResponseAPDU;
  1049.   present->PresentStatus = status;
  1050.   present->NumberOfRecordsReturned = recsRet;
  1051.   present->NextResultSetPosition = nextPos;
  1052.   present->ReferenceID = duplicateAny(refID);
  1053.   present->DatabaseDiagnosticRecords = records;
  1054.   return(present);  
  1055. }
  1056.  
  1057. /*----------------------------------------------------------------------*/
  1058.  
  1059. void 
  1060. freePresentResponseAPDU(present)
  1061. PresentResponseAPDU* present;
  1062.   freeAny(present->ReferenceID);
  1063.   s_free(present);
  1064. }
  1065.  
  1066. /*----------------------------------------------------------------------*/
  1067.  
  1068. char* 
  1069. writePresentResponseAPDU(present,buffer,len)
  1070. PresentResponseAPDU* present;
  1071. char* buffer;
  1072. long* len;
  1073. {
  1074.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  1075.   long size;
  1076.  
  1077.   RESERVE_SPACE_FOR_HEADER(len);
  1078.   
  1079.   buf = writePDUType(present->PDUType,buf,len);
  1080.   buf = writeBoolean(present->PresentStatus,buf,len);
  1081.   buf = writeBinaryInteger(present->NumberOfRecordsReturned,(size_t)3,buf,len);
  1082.   buf = writeBinaryInteger(present->NextResultSetPosition,(size_t)3,buf,len);
  1083.   buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
  1084.     
  1085.   /* go back and write the header-length-indicator */
  1086.   RELEASE_HEADER_SPACE(len);
  1087.   size = buf - buffer - HEADER_LEN; 
  1088.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  1089.  
  1090.   if (present->DatabaseDiagnosticRecords != NULL)
  1091.     buf = writePresentResponseInfo(present,buf,len);
  1092.     
  1093.   return(buf);
  1094. }
  1095.  
  1096. /*----------------------------------------------------------------------*/
  1097.  
  1098. char* 
  1099. readPresentResponseAPDU(present,buffer)
  1100. PresentResponseAPDU** present;
  1101. char* buffer;
  1102. {
  1103.   char* buf = buffer;
  1104.   long size;
  1105.   pdu_type pduType;
  1106.   boolean status;
  1107.   long recsRet,nextPos;
  1108.   any *refID = NULL;
  1109.   void* userInfo = NULL;
  1110.  
  1111.   /* read required part */
  1112.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  1113.   buf = readPDUType(&pduType,buf);
  1114.   buf = readBoolean(&status,buf);
  1115.   buf = readBinaryInteger(&recsRet,(size_t)3,buf);
  1116.   buf = readBinaryInteger(&nextPos,(size_t)3,buf);
  1117.  
  1118.   /* read optional part */
  1119.   while (buf < (buffer + size + HEADER_LEN)) 
  1120.    { data_tag tag = peekTag(buf);
  1121.      switch (tag)
  1122.       { case DT_ReferenceID:
  1123.           buf = readAny(&refID,buf);
  1124.           break;
  1125.         default:
  1126.           freeAny(refID);
  1127.           REPORT_READ_ERROR(buf);
  1128.           break;
  1129.       }
  1130.    }
  1131.   
  1132.   buf = readPresentResponseInfo(&userInfo,buf);
  1133.   if (buf == NULL)
  1134.     freeAny(refID);
  1135.   RETURN_ON_NULL(buf);
  1136.  
  1137.   /* construct the presentResponse object */
  1138.   *present = makePresentResponseAPDU(status,recsRet,nextPos,refID,userInfo);
  1139.  
  1140.   freeAny(refID);
  1141.   
  1142.   return(buf);
  1143. }
  1144.  
  1145. /*----------------------------------------------------------------------*/
  1146.  
  1147.  
  1148. #endif /* def NOTUSED */
  1149.